package com.itheima.alipay.controller;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.itheima.alipay.config.AliPayConfig;
import com.itheima.alipay.service.AliPayService;
import com.itheima.utils.RedisUtils;
import com.itheima.utils.ResultUtils;

import lombok.extern.slf4j.Slf4j;

@RequestMapping("alipay")
@RestController
@Slf4j
public class AliPayController {

    @Autowired
    private AliPayService payService;

    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 统一收单下单并支付页面接口调用
     */
    @GetMapping("trade/page/pay/{productId}")
    public JSONObject tradePagePay(@PathVariable Long productId) throws Exception {
        String formStr = payService.tradePagePay(productId);
        return ResultUtils.successData(formStr, "成功！");
    }

    // 支付成功回调方法
    @PostMapping(value = "notify")
    public String successNotify(@RequestParam Map<String, String> params) throws Exception {

        // 验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, aliPayConfig.getALIPAY_PUBLIC_KEY(), "utf-8",aliPayConfig.getSIGN_TYPE());

        // 必须返回stringl类型的结果，failure： 支付宝会不定时回调该方法， success就停止回调
        String result = "failure";

        // 验签失败
        if (!signVerified) {
            return result;
        }

        // TODO 校验 取出订单号做业务处理
        String orderNo = params.get("out_trade_no");

        // TODO 单位：元
        String totalAmount = params.get("total_amount");

        // TODO 商家id（PID）
        String sellerId = params.get("seller_id");

        // TODO 校验app_id
        String appId = params.get("app_id");

        // 交易状态
        String tradeStatus = params.get("trade_status");
        if (!"TRADE_FINISHED".equals(tradeStatus)){
            log.error("未支付成功");
            return result;
        }

        // 处理订单状态
        processOrder(params);

        return "success";
    }

    private String getOrderStatus(String orderNo) {
        // 根据订单号查询订单的支付状态
        return null;
    }

    private void savePaymentInfo(Map<String, String> params) {
        // 保存支付日志
    }

    /**
     * 当前系统由于网络原因没有将"success" 6个字符串发给支付宝, 支付宝会重复通知
     * 此时会再次修改订单状态(不影响)和新增支付日志(出现多条),为了防止重复通知, 要实现幂等性
     */
    private void processOrder(Map<String, String> params) {
        String orderNo = params.get("out_trade_no");

        // 为了防止支付宝多个服务器并发通知造成支付日多记录, 加锁控制
        Boolean result = redisUtils.setnx(orderNo, "lock", 30, TimeUnit.SECONDS);
        if (!result){
           return;
        }

        String orderStatus = getOrderStatus(orderNo);
        if (!"未支付".equals(orderStatus)){ // 不是未支付的不处理
            return;
        }
        // TODO 修改订单为已支付

        // 保存支付日志表
        savePaymentInfo(params);
    }
}
